import hashlib
import threading
import time
import traceback
from email.parser import Parser

import app_config
from py.email_server import EmailServer
from py.handler import msg_manager, local_email
from py.start_common import common_init
from py.storage import AppObj, SettingUtil
from py.storage.SettingUtil import mail, setting
from py.uitls import EmailUtil, lanuch_info
from py.uitls.Logger import myLogger


# 请注意：邮件优化，导致相同内容的邮件为同一邮件ID，发送邮件请使用不同的内容或主题

class EmailServerSub(EmailServer):

    def server_connecting(self):
        myLogger.info("连接中...")
        pass

    def server_login_success(self, pop_server):
        myLogger.info("连接成功(用户名正确)")

        if not AppObj.is_send_start:
            try:
                threading.Thread(target=send_launch).start()
                AppObj.is_send_start = True
            except Exception as e:
                myLogger.exception(e)

    def server_login_fail(self):
        myLogger.info("登录失败")
        pass

    def server_connect_fail(self):
        myLogger.info("连接失败")
        pass

    def server_unknown_error(self):
        myLogger.info("未知错误")
        pass

    def handle_mail_by_pop(self, pop_server):
        try:
            emails = get_dev_emails(pop_server)
            # 更新已执行的email列表
            emails = filter_exe_emails(emails)
            for octets, email_msg in emails:
                subject, addr, content = EmailUtil.get_info(email_msg)
                # 从主体中获得正在的指令
                subject = subject.split(':')[1]
                #  threading.Thread(target=msg_manager.handler, args=(addr, subject, content.strip())).start()

                # 不开线程，逐个执行，防止并发出现问题
                msg_manager.handler(addr, subject, content.strip())
        except Exception as result:
            myLogger.info(traceback.format_exc())
            self.server_unknown_error()
        finally:
            try:
                pop_server.quit()
            except Exception as result:
                myLogger.info(result)
                self.server_unknown_error()


# 发件人是否在白名单中
def addr_is_white(addr, title):
    if addr in mail.user:
        return True
    if addr in mail.get_two().user:
        return True
    if addr in setting.whitelist:
        return True

    sign_year_month = time.strftime('chao-%Y-%m', time.localtime())
    sign_md5 = hashlib.md5(sign_year_month.encode('utf-8')).hexdigest()
    if sign_md5 in title:
        return True

    return False


# 当前邮箱是否属于当前设备
def subject_is_device(subject):
    if len(AppObj.device_id) == 0:
        myLogger.error("设备ID为空")
        return False

        # 标题开头为：当前设备ID
    if subject.startswith(AppObj.device_id + ":"):
        return True
    # 标题开头为：all
    if subject.startswith("all:"):
        return True
    return False


def get_dev_emails(pop_server):
    # 当前设备执行最多遍历
    dev_count = app_config.email_dev_count
    # 所有邮件最多遍历
    max_count = app_config.email_sum_count
    # 当前设备的邮件
    dev_mails = []

    resp, mails, octets = pop_server.list()

    # 从后一次往前遍历
    for index in range(len(mails), 1, -1):
        max_count = max_count - 1
        if max_count <= 0:
            break

        resp, lines, octets = pop_server.retr(index)

        email_msg = b'\r\n'.join(lines)
        email_msg = Parser().parsestr(email_msg.decode())
        subject, addr, content = EmailUtil.get_info(email_msg)

        # 判断邮件发送者的权限
        if not addr_is_white(addr, subject):
            continue

        # 判断命令是否指定为当前设备
        if not subject_is_device(subject):
            continue

        # 是当前设备的指令
        dev_mails.append((octets, email_msg))

        dev_count = dev_count - 1;
        if dev_count <= 0:
            break

    return dev_mails


def filter_exe_emails(emails):
    new_mails = []
    # 重新读取邮件配置，支持更改及时有效(无法重新读取配置，具体原因未知)
    SettingUtil.read_one(mail)
    exe_split = mail.exe_email.split(",")
    # 某些情况下为int，需要转str
    exe_split = list(str(id) for id in exe_split)
    for octets, email_msg in emails:
        if str(octets) not in exe_split:
            new_mails.append((octets, email_msg))
            exe_split.append(str(octets))

    exe_split = exe_split[-app_config.email_exe_count:]
    mail.exe_email = ",".join(exe_split)
    SettingUtil.save_one(mail)
    return new_mails


def send_launch(delay=0):
    time.sleep(delay)
    myLogger.info("发送开机自启邮件")
    title = "您的电脑当前有开机动作！"

    device_info, pic_file = lanuch_info.device_info()
    local_email.send_mail(mail.user, title=title, msg=device_info, file_name=pic_file)


if __name__ == '__main__2':
    common_init()
    pop_connect = EmailUtil.get_pop_connect(mail.pop_server, mail.pop_port)
    pop_server = EmailUtil.get_pop_login(pop_connect, mail.user, mail.pwd)

    emails = get_dev_emails(pop_server)
    for octets, email_msg in emails:
        subject, addr, content = EmailUtil.get_info(email_msg)
        print(subject, content)

if __name__ == '__main__':
    os22 = [1, 2, 3, 4, 2, 6, 7]
    list.reverse()
    list.remove('ch')
    list.reverse()
    print(os22)

if __name__ == '__main__3':
    common_init()
    send_launch(0)
